#!/bin/bash
# 脚本解释器 强制设置为 bash
if [ "$BASH" != "/bin/bash" -a "$BASH" != "/usr/bin/bash" ]; then
   bash $0 "$@"
   exit $?
fi

function error(){
    echo -e "\033[1;31m"$1"\033[0m"
    exit 1
}
# root权限执行此脚本
[ "${UID}" -ne 0 ] && error "请使用root权限执行"

CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
cd ${CURRENT_DIR}
# CPU1上预留的cpu数
RESERVE_CPU1=4
# CPU2上预留的cpu数
RESERVE_CPU2=0
# GPU是否跨NUMA。即是否忽略numa，qemu实例根据服务器特性，不跨numa。
GPU_across_NUMA=0

# GPU数量
NUM_OF_GPU=$(lspci|grep AMD|grep 5100|wc -l)
# 所有的cpu数
ALL_CPU=$(lscpu|grep -w "CPU(s)"|head -n 1|awk '{print $2}')
# numa_node数
NUM_OF_NUMA=$(lscpu|grep "NUMA node(s)"|awk '{print $3}')
# 启动xorg
for((i=0;i<${NUM_OF_GPU};i++))
do
    ps -ef|grep -v "grep"|grep xorg${i}
    if [ $? -ne 0 ]
    then
        nohup Xorg :${i} -config /etc/X11/xorg${i}.conf -sharevts &
        sleep 5
    fi
done
# 判断是否有第一个参数
if [ -z $1 ]
then
    error "usage: <start_num> [end_num]"
fi

if [ "$1" -gt 0 ] 2>/dev/null ; then
    echo "" > /dev/null
else
    error "Invalid value.Please enter a positive integer."
fi

# 第一个参数是最小数量(MIN)
MIN=$1
# 判断是否有第二个参数，第二个参数为最大数量(MAX)
if [ -z $2 ]
then
    MAX=$MIN
else
    if [ "$2" -gt 0 ] 2>/dev/null ; then
        echo "" > /dev/null
    else
        error "Invalid value.Please enter a positive integer."
    fi
    MAX=$2
fi

# 输出创建的实例数量或范围
if [ $MIN -lt $MAX ]
then
    echo "start qemu $MIN ~ $MAX"
elif [ $MIN -eq $MAX ]
then
    echo "start qemu $MIN"
else
    error "start_num must be less than end_num"
fi

pci_ids=$(lspci|grep AMD|grep 5100|awk '{print $1}')
j=0
k=0
s=0
for pci_id in ${pci_ids}
do
    if [ ${#pci_id} -eq 7 ]
    then
        r_pci_id="0000:${pci_id}"
    else
        r_pci_id="${pci_id}"
    fi
    gpu_node=$(ls /sys/bus/pci/devices/${r_pci_id}/drm/|grep renderD)
    numa_node=$(cat /sys/bus/pci/devices/${r_pci_id}/numa_node)
    gpu_card_id=$(ls /sys/bus/pci/devices/${r_pci_id}/drm/|grep card)
    echo gpu_card_id = ${gpu_card_id}
    echo high > /sys/class/drm/${gpu_card_id}/device/power_dpm_force_performance_level
    echo "pci_id = ${pci_id}--gpu_node = ${gpu_node}--numa_node = ${numa_node}"
    all_gpu[s]=${gpu_node}
    let s++
    if [ ${numa_node} -lt $((NUM_OF_NUMA/2)) ]
    then
        cpu1[j]=${gpu_node}
        let j++
    else
        cpu2[k]=${gpu_node}
        let k++
    fi
done
cpu1_gpu_num=${#cpu1[@]}
cpu2_gpu_num=${#cpu2[@]}
all_gpu_num=${#all_gpu[@]}
if [ ${GPU_across_NUMA} -eq 0 ]
then
    if [ ${cpu1_gpu_num} -eq 0 ]
    then
        RESERVE_CPU1=$((${ALL_CPU}/2))
    fi
    if [ ${cpu2_gpu_num} -eq 0 ]
    then
        RESERVE_CPU2=$((${ALL_CPU}/2))
    fi
fi
NUM_OF_CPU1=$(((${ALL_CPU}/2)-${RESERVE_CPU1}))
NUM_OF_CPU2=$(((${ALL_CPU}/2)-${RESERVE_CPU2}))
# 多少组CPU核 一组4个
GROUP_OF_CPU1=$((${NUM_OF_CPU1}/4))
GROUP_OF_CPU2=$((${NUM_OF_CPU2}/4))
GROUP_OF_CPU=$((${GROUP_OF_CPU1}+${GROUP_OF_CPU2}))

for i in `seq ${MIN} ${MAX}`
do
    echo "---------$i----------"
    starttime=$(date +'%Y-%m-%d %H:%M:%S')
    echo "starttime = ${starttime}"
    start_seconds=$(date --date="${starttime}" +%s);
    # 计算绑cpu
    if [ $((($i-1)%${GROUP_OF_CPU})) -lt ${GROUP_OF_CPU1} ]
    then
        CPU_START=$((((($i-1)%${GROUP_OF_CPU})*4)+${RESERVE_CPU1}))
    else
        CPU_START=$((((($i-1)%${GROUP_OF_CPU})*4)+${RESERVE_CPU2}+${RESERVE_CPU1}))
    fi
    CPU_END=$((${CPU_START}+3))
    CPUS="${CPU_START}-${CPU_END}"
    echo "CPUS = ${CPUS}"
    # 计算绑numa和GPU
    if [ ${CPU_END} -lt $((${ALL_CPU}/2)) ]
    then
        if [ ${NUM_OF_NUMA} = 4 ]
        then
            MEM="0,1"
        elif [ ${NUM_OF_NUMA} = 2 ]
        then
            MEM="0"
        else
            echo "numa node(s):${NUM_OF_NUMA} ??"
            exit 1
        fi                        
    else
        if [ ${NUM_OF_NUMA} = 4 ]
        then
            MEM="2,3"
        elif [ ${NUM_OF_NUMA} = 2 ]
        then
            MEM="1"
        else
            echo "numa node(s):${NUM_OF_NUMA} ??"
            exit 1
        fi                
    fi
    if [ ${GPU_across_NUMA} -eq 1 ]
    then
        n=$((${i}%${all_gpu_num}))
    else
        if [ ${CPU_END} -lt $((${ALL_CPU}/2)) ]
        then
            n=$((${i}%${cpu1_gpu_num}))
        else
            n=$((${i}%${cpu2_gpu_num}))
        fi
    fi
    # GPU="renderD128"
    echo "MEM : $MEM"
    # 计算虚拟机port，从5554开始，每多创建一个avd实例，端口号加2
    port=$((5554+2*(i-1)))
    echo "port : ${port}"
    echo "CPU : ${CPUS}"

    # 创建虚拟机
    android create avd --name qemu_android_$i --target android-28 --abi arm64-v8a --device "Nexus 4" --skin "720x1280" --sdcard 4096M --force
    sleep 5
    # 导入环境变量
    echo "display n = ${n}"
    export DISPLAY=:${n}
    # 启动虚拟机

    nohup numactl -C ${CPUS} -m ${MEM} emulator -avd qemu_android_${i} -port ${port} -partition-size 4096 -no-window -cores 4 -gpu host -qemu --enable-kvm -m 4096 -vnc :${i} &
    sleep 5
    endtime=$(date +'%Y-%m-%d %H:%M:%S')
    echo "endtime = ${endtime}"
    end_seconds=$(date --date="${endtime}" +%s);
    echo "Running："$((end_seconds-start_seconds))"s"
done

echo ""
echo "--------------done-------------"
exit 0

